import com.google.common.util.concurrent.ThreadFactoryBuilder;
import kt.Utils.ThreadPoolManager;
import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        int corePoolSize = Runtime.getRuntime().availableProcessors();
        // 池中允许的最大线程数
        final int maxPoolSize = 9;
        // 线程池中的空闲线程所能持续的最长时间
        final long keepAliveTime = 3L;
        // 时间单位
        final TimeUnit unit = TimeUnit.MILLISECONDS;
        // 线程队列
        final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
        // 线程工厂
        final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("operation-%d").build();
        System.out.println("a = " + corePoolSize);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        threadPoolExecutor.prestartAllCoreThreads(); // 预启动所有核心线程 更快
//        ThreadPoolManager threadPoolManager = ThreadPoolManager.Companion.getInstance();
//        ThreadPoolExecutor threadPoolExecutor = threadPoolManager.getThreadPool("test");

        gdal.AllRegister();
        String fileName_tif = "E:\\Test\\database\\raster_dataCGCS2000\\宜林地.tif";
        //String fileName = "D:\\TestDta\\images\\zy3_92_126_20140926_14_fus.tif";
        Dataset hDataset = gdal.Open(fileName_tif, gdalconstConstants.GA_ReadOnly);
        //Dataset hDataset1 = gdal.Open(fileName, gdalconstConstants.GA_ReadOnly);
        List<Dataset> list = new ArrayList<Dataset>();
        list.add(hDataset);
        //list.add(hDataset1);
        if (list.get(0) == null) {
            System.err.println("GDALOpen failed - " + gdal.GetLastErrorNo());
            System.err.println(gdal.GetLastErrorMsg());
            System.exit(1);
        }

        Driver hDriver = list.get(0).GetDriver();
        System.out.println("Driver: " + hDriver.getShortName() + "/" + hDriver.getLongName());
        System.out.println("Size is " + list.get(0).getRasterXSize() + ", " + list.get(0).getRasterYSize());

        int iXSize = list.get(0).getRasterXSize();
        int iYSize = list.get(0).getRasterYSize();

        //宽、高、波段数
        int b = list.get(0).getRasterCount();
        //从波段中获取影像的数据类型，gdal中波段索引从1开始
        int dataType = list.get(0).GetRasterBand(1).GetRasterDataType();
        //六参数信息
        double[] geoTransform = list.get(0).GetGeoTransform();

        //设置要裁剪的起始像元位置，以及各方向的像元数
        //这里表示从像元(5000, 5000)开始，x方向和y方向各裁剪1000个像元
        //最终结果就是一幅1000*1000的影像
        int startX = 0;
        int startY = 0;
        //每次读取x数量
        int clipX = iXSize;
        //每次读取y数量
        int clipY = 1;

        //计算裁剪后的左上角坐标
        geoTransform[0] = geoTransform[0] + startX * geoTransform[1] + startY * geoTransform[2];
        geoTransform[3] = geoTransform[3] + startX * geoTransform[4] + startY * geoTransform[5];
        //创建结果图像
        Driver driver = gdal.GetDriverByName("GTIFF");
        File file = new File("E:\\Test\\result");
        if (!file.exists()) {
            file.mkdirs();
        }
        Dataset outputDs = driver.Create(file.getPath() + "\\result1.tif", iXSize, iYSize, b, dataType);
        outputDs.SetGeoTransform(geoTransform);
        outputDs.SetProjection(list.get(0).GetProjection());
        long millis = System.currentTimeMillis();



        for(int j = 1; j <= b; j++){
            List<Band> bandList = new ArrayList<Band>();
            for(int m = 0;m<list.size();m++){
                bandList.add(list.get(m).GetRasterBand(j));
            }
            Double[] nodata = new Double[1];
            if (bandList.get(0) == null) {
                continue;
            }
            bandList.get(0).GetNoDataValue(nodata);
            Band desBand = outputDs.GetRasterBand(j);
            //desBand.SetNoDataValue(nodata[0]);
            //按band读取
            try {
                for(int i = 0; i < iYSize; i += clipY){
                    threadPoolExecutor.execute(new ThreadUtil(i,clipY,iYSize,clipX,nodata,bandList,desBand));
                }
                threadPoolExecutor.shutdown();
                while (true) {//等待所有线程执行完毕
                    if (threadPoolExecutor.isTerminated()) {
                        System.out.println("所有的子线程都结束了！");
                        break;
                    }
                }
            } catch (Exception e) {
                System.out.println("其他错误:"+e.toString());
            }finally {
                System.out.println("thread shutdown");
                threadPoolExecutor.shutdownNow();
            }

            hDataset.delete();
            //hDataset1.delete();
            outputDs.delete();
            gdal.GDALDestroyDriverManager();

            long millis2 = System.currentTimeMillis();
            System.out.println(millis2-millis);

        }
        // 可选
    }

}
